/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.gui;

import java.awt.*;
import java.io.*;
import java.util.*;
import java.text.*;
import javax.swing.*;

import blueprint4j.db.*;
import blueprint4j.utils.*;

import java.sql.SQLException;


public class Clock extends JPanel implements Runnable {
    private static Font time_font=null;
    private static Font date_font=null;
    public static Date clock_time = null;
    
    private static ClockNotification clock_notify= null;
    private boolean enable_notify = false;
    private static int cntt = 0;
    
    static {
        
        try {
            InputStream input=Clock.class.getClassLoader().getResourceAsStream("fonts/Digire__.ttf");
            time_font=Font.createFont(Font.TRUETYPE_FONT,input);
            input.close();
            time_font=time_font.deriveFont(Font.PLAIN,32f);
            date_font=new Font("Courier", Font.BOLD, 12);
        } catch (Exception e) {
            Log.critical.out(e);
            System.exit(-1);
        }
    }
    
    private boolean thread_running=false;
    private boolean thread_shutdown=true;
    private JLabel label_date=new JLabel();
    private JLabel label_time=new JLabel();
    
    
    Clock(boolean enable_notify) {
        super(new BorderLayout());
        this.enable_notify = enable_notify;
        init();
    }
    
    //Clock() {this(false);}
    
    public void paint(Graphics g) {
        Graphics2D g2=(Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        super.paint(g);
    }
    
    private void init() {
        setBackground(new Color(0x29,0x42,0x2a));
        setBorder(BorderFactory.createLoweredBevelBorder());
        label_date.setForeground(new Color(0x40,0xff,0x2d));
        label_time.setForeground(new Color(0x40,0xff,0x2d));
        label_date.setFont(date_font);
        label_time.setFont(time_font);
        label_date.setHorizontalAlignment(JLabel.CENTER);
        label_time.setHorizontalAlignment(JLabel.CENTER);
        JPanel panel=new JPanel(new BorderLayout());
        panel.setOpaque(false);
        panel.add(label_date);
        add(panel,BorderLayout.NORTH);
        panel=new JPanel(new BorderLayout());
        panel.setOpaque(false);
        panel.add(label_time);
        label_date.setBorder(BorderFactory.createEmptyBorder(2,0,0,2));
        label_time.setBorder(BorderFactory.createEmptyBorder(0,0,0,15));
        add(panel,BorderLayout.CENTER);
    }
    
    public void addNotify() {
        try {
            super.addNotify();
            if (!thread_running) {
                thread_shutdown=false;
                new Thread(this).start();
                if (enable_notify) {
                    clock_notify = new ClockNotification(DBTools.getNDC(),this);
                    ThreadSchedule.add(clock_notify);
                }
            }
        } catch (Throwable th) {
            Log.debug.out(th);
        }
    }
    
    public void removeNotify() {
        super.removeNotify();
        thread_shutdown=true;
        while (thread_running) {}
    }
    
    public void run() {
        thread_running=true;
        while (!thread_shutdown) {
            int second=-1;
            Calendar calendar=Calendar.getInstance();
            SimpleDateFormat format_date=new SimpleDateFormat("dd MMM yyyy");
            SimpleDateFormat[] format_time=
                    new SimpleDateFormat[]{
                new SimpleDateFormat("HH:mm:ss"),
                new SimpleDateFormat("HH.mm.ss")
            };
            try {
                Date date=null;
                if (clock_time != null) {
                    date = clock_time;
                } else {
                    date=new Date();
                }
                calendar.setTime(date);
                if (second!=(calendar.get(Calendar.MILLISECOND)/500)) {
                    second=calendar.get(Calendar.MILLISECOND)/500;
                    label_time.setText(format_time[second&1].format(date));
                    label_date.setText(format_date.format(date));
                }
                Thread.sleep(50);
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
        thread_running=false;
    }
    
    protected void notifyInternal(Color color) {
        Color last = this.getBackground();
        double rm = (color.getRed() - last.getRed()) / 5.0,
                gm= (color.getGreen()-last.getGreen())/5.0,
                bm = (color.getBlue() - last.getBlue())/5.0;
        for (int i= 0;i < 5;i++) {
            setBackground(new Color(
                    (int)Math.round(last.getRed()+i*rm),
                    (int)Math.round(last.getGreen()+i*gm),
                    (int)Math.round(last.getBlue()+i*bm))
                    );
            try {Thread.sleep(50);} catch (InterruptedException ie) {}
        }
        for (int i= 0;i < 5;i++) {
            setBackground(new Color(
                    (int)Math.round(color.getRed()-i*rm),
                    (int)Math.round(color.getGreen()-i*gm),
                    (int)Math.round(color.getBlue()-i*bm))
                    );
            try {Thread.sleep(50);} catch (InterruptedException ie) {}
        }
        setBackground(last);
    }
    
    public static void notify(Class p_class,Color color) {
        try {
            ClockNotification notify = (ClockNotification) new ClockNotification(DBTools.getDLC()).find("class_name = '"+p_class.getName()+"'");
            if (notify == null){
                notify = new ClockNotification(DBTools.getDLC());
                notify.class_name.set(p_class.getName());
            }
            notify.notify_color.set(color);
            notify.time_stamp.set(new Date());
            notify.save();
        } catch (Throwable th) {
            Log.debug.out(th);
        }
    }
    
    public static class ClockNotification extends Entity implements ThreadScheduable {
        private TableName table_name = new TableName("d_clock_notifications",this);
        
        public FieldUnique id = new FieldUnique("id",0,"Id",this);
        public FieldString class_name = new FieldString("class_name",0,"Class Name",250,this);
        public FieldColor notify_color= new FieldColor("notify_color",0,"Color",this);
        public FieldTimestamp time_stamp = new FieldTimestamp("time_stamp",0,"Timestamp",this);
        public FieldDateTime last_notify = new FieldDateTime("last_notify",0,"Last Notification",this);
        private boolean keep_alive = true;
        
        private Clock clock = null;
        
        public ClockNotification() {super();}
        
        public ClockNotification(DBConnection dbcon) throws DataException,SQLException {
            super(dbcon);
        }
        
        public ClockNotification(DBConnection dbcon,Clock clock) throws SQLException {
            super(dbcon);
            this.clock = clock;
        }
        
        public Entity getNewInstance() {return new ClockNotification();}
        
        public boolean keepAlive() {return keep_alive;}
        public int sleepTime(){ return 2000;}
        public void stop() {keep_alive = false;}
        
        public void process()
        throws Throwable {
            DBConnection dbcon = DBTools.getNDC();
            try {
                for (
                        ClockNotification notify =
                        (ClockNotification)
                        new ClockNotification(dbcon).find(
                        "time_stamp <> last_notify or last_notify is null"
                        );
                notify != null;
                notify =(ClockNotification) notify.getNextEntity()
                ) {
                    clock.notifyInternal(notify.notify_color.get());
                    java.sql.Statement smt = dbcon.createStatement();
                    smt.execute("update d_clock_notifications set last_notify = time_stamp where id = '"+notify.id.get()+"'");
                    dbcon.commit();
                    smt.close();
                }
            } finally {
                dbcon.close();
            }
        }
        
        public void close() throws Throwable {}//getConnection().close();}
    }
}

